import * as THREE from "three";
// import { default as CSM } from 'three-csm';
import type Viewer from "../viewer";
import { SkyShader } from '../../../../assets/shaders/SkyShader.ts';



export default class Sky extends THREE.Object3D {
  public viewer: Viewer;

  // public csm: CSM;

  public sunPosition: THREE.Vector3 = new THREE.Vector3();


  set theta(value: number) {
    this._theta = value;
  }

  set phi(value: number) {
    this._phi = value;
  }

  private _phi: number = 50;
  private _theta: number = 145;

  private hemiLight: THREE.HemisphereLight;
  private maxHemiIntensity: number = 0.9;
  private minHemiIntensity: number = 0.3;

  private skyMesh: THREE.Mesh;
  private skyMaterial: THREE.ShaderMaterial;

  constructor(viewer: Viewer) {
    super();
    this.viewer = viewer;

    // 初始化渲染天空
    this.skyMaterial = new THREE.ShaderMaterial({
      uniforms: THREE.UniformsUtils.clone(SkyShader.uniforms),
      fragmentShader: SkyShader.fragmentShader,
      vertexShader: SkyShader.vertexShader,
      side: THREE.BackSide
    })

    this.skyMesh = new THREE.Mesh(
      new THREE.SphereGeometry(1000, 24, 12),
      this.skyMaterial
    )

    this.attach(this.skyMesh);

    this.viewer.graphWorld.add(this)

    // Ambient light
    this.hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 1.0);
    this.refreshHemiIntensity();
    this.hemiLight.color.setHSL(0.59, 0.4, 0.6);
    this.hemiLight.groundColor.setHSL(0.095, 0.2, 0.75);
    this.hemiLight.position.set(0, 50, 0);
    this.viewer.graphWorld.add(this.hemiLight);
    this.refreshSunPosition();

    // this.csm = new CSM({
    //   lightIntensity: 2.5,
    //   cascades: 3,
    //   shadowMapSize: 2048,
    //   camera: this.viewer.camera,
    //   parent: this.viewer.graphWorld,
    //   mode: 'custom',
    //   customSplitsCallback: (amount, near, far) => {
    //     let arr = [];

    //     for (let i = amount - 1; i >= 0; i--) {
    //       arr.push(Math.pow(1 / 4, i));
    //     }

    //     return arr;
    //   }
    // })
  }

  public refreshSunPosition(): void {
    const sunDistance = 10;

    this.sunPosition.x = sunDistance * Math.sin(this._theta * Math.PI / 180) * Math.cos(this._phi * Math.PI / 180);
    this.sunPosition.y = sunDistance * Math.sin(this._phi * Math.PI / 180);
    this.sunPosition.z = sunDistance * Math.cos(this._theta * Math.PI / 180) * Math.cos(this._phi * Math.PI / 180);

    this.skyMaterial.uniforms.sunPosition.value.copy(this.sunPosition);
    this.skyMaterial.uniforms.cameraPos.value.copy(this.viewer.camera.position);
  }

  public refreshHemiIntensity(): void {
    this.hemiLight.intensity = this.minHemiIntensity + Math.pow(1 - (Math.abs(this._phi - 90) / 90), 0.25) * (this.maxHemiIntensity - this.minHemiIntensity);
  }

}